﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MPF.Klase.Pomocne
{
    /// <summary>
    /// Predstavlja jednu klasu ponavljanja.
    /// Element "element" javlja se u Listi na lokacijama sa indeksima "lokacije"
    /// </summary>
    /// <typeparam name="T"></typeparam>
    class KlasaPonavljanja<T>
    {
        public T PonavljajuciElement { get; set; }
        public List<int> Lokacije { get; set; }

        public KlasaPonavljanja(T element, int lokacija)
        {
            PonavljajuciElement = element;
            Lokacije = new List<int>();
            Lokacije.Add(lokacija);
        }

        public KlasaPonavljanja(T element, List<int> lokacije)
        {
            PonavljajuciElement = element;
            Lokacije = lokacije;
        }

        public bool PonavljaSe
        {
            get
            {
                return Lokacije.Count > 1;
            }
        }
    }


    /// <summary>
    /// Lista elemenata tipa T sa !nepromjenjivim! brojem elemenata.
    /// Detektuje ponavljanja elemenata te vraca indekse koji su pod ponavljanjem ukupno ili po klasama.
    /// </summary>
    class SpecijaliziranaLista<T>
    {
        public List<KlasaPonavljanja<T>> klasePonavljanja { get; set; }

        public SpecijaliziranaLista()
        {
            klasePonavljanja = new List<KlasaPonavljanja<T>>();
        }

        /// <summary>
        /// garantovano ne smije biti vec postojeci
        /// </summary>
        /// <param name="element"></param>
        public void dodajNoviElement(T element)
        {
            klasePonavljanja.Add(new KlasaPonavljanja<T>(element, klasePonavljanja.Count));
        }

        /// <summary>
        /// Osvjezava klase ponavljanja.
        /// </summary>
        /// <param name="oldVal">Stara vrijednost kljuca</param>
        /// <param name="newVal">Nova vrijednost kljuca</param>
        /// <param name="location">Lokacija koja je nepromjenjiva</param>
        public void refresh(T oldVal, T newVal, int location)
        {
            int indKlase = -1;
            for (int i = 0; i < klasePonavljanja.Count; i++)
            {
                if (EqualityComparer<T>.Default.Equals(klasePonavljanja[i].PonavljajuciElement, oldVal))
                {
                    indKlase = i;
                }
            }

            if (indKlase == -1) throw new Exception("Element kojeg osvjezavate ne postoji!");

            // vise se tu ne ponavlja
            klasePonavljanja[indKlase].Lokacije.Remove(location);

            // ako vise niko ne pripada datoj klasi ponavljanja
            if (klasePonavljanja[indKlase].Lokacije.Count == 0) klasePonavljanja.RemoveAt(indKlase);

            // trazimo mu novo mjesto pod suncem :)
            indKlase = -1;
            for (int i = 0; i < klasePonavljanja.Count; i++)
            {
                if (EqualityComparer<T>.Default.Equals(klasePonavljanja[i].PonavljajuciElement, newVal))
                {
                    indKlase = i;
                }
            }

            //ako je potpuno nova klasa ponavljanja
            if (indKlase == -1)
            {
                klasePonavljanja.Add(new KlasaPonavljanja<T>(newVal, location));
                return;
            }

            //ako vec postoji
            klasePonavljanja[indKlase].Lokacije.Add(location);
        }

        public List<int> IndeksiPodPonavljanjem
        {
            get
            {
                List<int> retVar = new List<int>();
                foreach (KlasaPonavljanja<T> kp in klasePonavljanja)
                {
                    if (kp.PonavljaSe)
                    {
                        retVar.AddRange(kp.Lokacije);
                    }
                }
                return retVar;
            }
        }

    }
}
